'''
Created on 11/06/2010

@author: Will


'''

from objects.realObject import RealObject
from pyglet.window import key
from objects.car.frontWheel import FrontWheel
from objects.car.rearWheel import RearWheel
import math
from utils import globals
from pymunk import Vec2d
from utils import time




class Car(RealObject):
    

    
    def __init__(self,x,y,rot,world):
        RealObject.__init__(self, x, y, rot,"car.png",mass1 = 1500)
        self.isCar = True
        self.isBeingControlled = False
        self.world = world
        self.setupWheels()
        self.POWER = 140000
        self.wheelTurnStep = 2
        self.lastPosition = self.position
        self.WheelLimitAngle = math.pi/2
        
        
    def setupWheels(self):
             
        self.rearLeftWheel = RearWheel(self,self.world)
        
        self.rearLeftWheel.offset = -self.getRelWidth(),-self.getRelHeight()*0.8
        self.rearLeftWheel.position = self.getRearLeftWheelPosition()
        
        self.rearRightWheel = RearWheel(self,self.world)
        
        self.rearRightWheel.offset = self.getRelWidth(),-self.getRelHeight()*0.8
        self.rearRightWheel.position = self.getRearRightWheelPosition()

        
        self.frontLeftWheel = FrontWheel(self,self.world)
        self.frontLeftWheel.offset = -self.getRelWidth(),self.getRelHeight()*0.8
        self.frontLeftWheel.position = self.getFrontLeftWheelPosition()
        
        self.frontRightWheel = FrontWheel(self,self.world)
        self.frontRightWheel.offset = self.getRelWidth(),self.getRelHeight()*0.8
        self.frontRightWheel.position = self.getFrontRightWheelPosition()

    def getRearLeftWheelPosition(self):
        point = self.getRotatedPoint(self.rearLeftWheel.offset)
        return self.body.position.x + point.x, self.body.position.y + point.y
    
    def getRearRightWheelPosition(self):
        point = self.getRotatedPoint(self.rearRightWheel.offset)        
        return self.body.position.x + point.x, self.body.position.y + point.y
        
    def getFrontLeftWheelPosition(self):
        point = self.getRotatedPoint(self.frontLeftWheel.offset)
        return self.body.position.x + point.x, self.body.position.y + point.y
    
    def getFrontRightWheelPosition(self):
        point = self.getRotatedPoint(self.frontRightWheel.offset)        
        return self.body.position.x + point.x, self.body.position.y + point.y
                      
    def tick(self,keyboard):
       
        self.physicsUpdate()
        globals.hudInstance.downVar = int(self.getSpeed()/3.6)

        if self.isBeingControlled:
            if(keyboard[key.UP]):
                self.accelerate()
            if(keyboard[key.DOWN]):
                if (self.getForwardVelocity() > 10):
                    self.brake()
                else:
                    self.reverse()
             
            if(keyboard[key.SPACE]):
                self.handBrake()
                
            if(keyboard[key.LEFT]):
                self.turnWheelsLeft()
                
            if(keyboard[key.RIGHT]):
                self.turnWheelsRight()
                
        self.holdWheelsInPlace()   
        for i in self.childs:
            i.tick()
            
    def getForwardVelocity(self):
        velocidade = self.body._get_velocity().get_length()
        
        velAngle = self.body._get_velocity().get_angle()
        relAngle = self.body._get_angle() +math.pi/2 - velAngle
        #print math.degrees(relAngle)
        result = Vec2d(0,math.cos(relAngle)*velocidade).rotated(self.body._get_angle()).get_length()
        if math.cos(relAngle) < 0:
            return -result
        
        return result        
            
    def brake(self):
        self.frontLeftWheel.braking = True
        self.frontRightWheel.braking = True
     
    def handBrake(self):
        self.rearLeftWheel.braking = True
        self.rearRightWheel.braking = True
        
    def accelerate(self):
        dt = time.getDt()
        impulso = Vec2d(self.POWER*dt,0).rotated(self.frontLeftWheel.getRotation())
        self.body.apply_impulse((impulso.x,impulso.y) , (self.getRotatedPoint(self.frontLeftWheel.offset) ))
                
        impulso = Vec2d(self.POWER*dt,0).rotated(self.frontRightWheel.getRotation())
               
        self.body.apply_impulse((impulso.x,impulso.y) , (self.getRotatedPoint(self.frontRightWheel.offset) ))
            
        
    def reverse(self):
        dt = time.getDt()
        impulso = Vec2d(-self.POWER*dt,0).rotated(self.frontLeftWheel.getRotation())
        self.body.apply_impulse((impulso.x,impulso.y) , (self.getRotatedPoint(self.frontLeftWheel.offset) ))
                
        impulso = Vec2d(-self.POWER*dt,0).rotated(self.frontRightWheel.getRotation())
               
        self.body.apply_impulse((impulso.x,impulso.y) , (self.getRotatedPoint(self.frontRightWheel.offset) ))
            
        
    def holdWheelsInPlace(self):
        diference = self.body._get_angle() - self.frontLeftWheel.rotation
        if diference > self.WheelLimitAngle:
            self.frontLeftWheel.rotation = -self.WheelLimitAngle + self.body._get_angle()
        if diference < -self.WheelLimitAngle:
            self.frontLeftWheel.rotation =  self.WheelLimitAngle + self.body._get_angle()
        diference = self.body._get_angle() - self.frontRightWheel.rotation
        if diference > self.WheelLimitAngle:
            self.frontRightWheel.rotation = -self.WheelLimitAngle + self.body._get_angle()
        if diference < -self.WheelLimitAngle:
            self.frontRightWheel.rotation =  self.WheelLimitAngle + self.body._get_angle()
    
    def turnWheelsLeft(self):
        self.frontLeftWheel.rotation = self.frontLeftWheel.rotation + self.wheelTurnStep * time.getDt()
        self.frontRightWheel.rotation = self.frontRightWheel.rotation + self.wheelTurnStep* time.getDt()
        
        
    def turnWheelsRight(self):
        self.frontLeftWheel.rotation = self.frontLeftWheel.rotation - self.wheelTurnStep* time.getDt()
        self.frontRightWheel.rotation = self.frontRightWheel.rotation - self.wheelTurnStep* time.getDt()

    def physicsUpdate(self):       
    
        airForce = math.pow(self.body._get_velocity().get_length(),2)*0.4257
        velocity = Vec2d(self.lastPosition[0]-self.position[0],self.lastPosition[1]-self.position[1])
        airforce = velocity.normalized()*airForce*time.getDt()
        friction = self.body._get_velocity()* -5
        
        
        self.lastPosition = self.position
        forces = []
        forces.append(self.rearLeftWheel.tryToMoveTo(self.getRearLeftWheelPosition()))
        forces.append(self.rearRightWheel.tryToMoveTo(self.getRearRightWheelPosition()))
        forces.append(self.frontLeftWheel.tryToMoveTo(self.getFrontLeftWheelPosition()))
        forces.append(self.frontRightWheel.tryToMoveTo(self.getFrontRightWheelPosition()))
        forces.append((airforce,(0,0)))
        forces.append((friction,(0,0)))
        
        
        for f in forces:
            self.body.apply_impulse(f[0],f[1])
            
        self.x = self.body.position.x
        self.y = self.body.position.y
        
        self.rotation = math.degrees(self.body._get_angle())
        if self.rotation <= math.pi:
            self.rotation = math.pi - self.rotation
        else:
            self.rotation = 2*math.pi - self.rotation